#include "CH58x_common.h"
#include "zqm_global.h"
#include "zqm_module.h"
#include "hal_disp_key.h"

const unsigned int KEY_SCAN_PERIOD = 50;
// external driver 
extern void DrvDispKeyInit(void);
extern void DrvDisplay(uint8_t brightness);
extern uint8_t DrvReadKeys(void);
extern void LedCodecItem(disp_item_t item_no, uint8_t isOn);

// hal disp functions ----------------------------------------------------------------------------------------------- 
static uint8_t disp_brightness = 0x07;					// set 0-7 level light
char disp_buff[LED_ITEM_NUM][2] = { 0 };			// display buffer{char1, char2}:    char1 -- 0 is a icon or ascii codes; char2 -- mode 
uint32_t key_state[ZQ_KEY_NUM]; 		// ZQ_KEY_NUM key 状态: bit31:0 - key up; bit31:1 - key down; bit0 - 30: 键按下持续时间, ms, 
void DispKeyInit(void)
{
	DrvDispKeyInit();
	// simulator self-test, turn on 1s and turn off 1s
    DispAllItems(1);        // self test. light all on/off 1s
	M0DelayMs(1000);
    DispAllItems(0);
	M0DelayMs(1000);
}

// refresh display memory, codec all the display items from disp_buff to display memory every TASK_PERIOD
void DispRefresh( void ) 
{
	for(int i = 0; i < LED_ITEM_NUM; i++){		
		switch (disp_buff[i][1])
		{
			case disp_mode_off:
				LedCodecItem(i, 0);
				break;
			case disp_mode_on:
				LedCodecItem(i, 1);
				break;
			case disp_mode_flash_05:	// 0.5Hz flash
				// kg modify 20231030, 下面注释的写法, 如果不是整500ms切换, 会让灯看上去闪烁, 修改为只在0.5Hz半周期处切换：
				//if ((zq_timer_50ms % 500) < 250)	
				//	LedCodecItem(i, 1);
				//else
				//	LedCodecItem(i, 0);
				// light on at the begining of full wave and off at the begining of half wave
				if ((zq_timer_50ms % 250) == 0) {
					if ((zq_timer_50ms % 500) == 0)
						LedCodecItem(i, 1);
					else
						LedCodecItem(i, 0);
				}
				break;
			case disp_mode_flash_1:		// 1Hz flash
				// kg modify 20231030, 下面注释的写法, 如果不是整秒切换, 会让灯看上去闪烁, 修改为只在1Hz半周期处切换：
				//if ((zq_timer_50ms % 1000) < 500)	
				//	LedCodecItem(i, 1);
				//else
				//	LedCodecItem(i, 0);
				// light on at the begining of full wave and off at the begining of half wave
				if ((zq_timer_50ms % 500) == 0) {
					if ((zq_timer_50ms % 1000) == 0)
						LedCodecItem(i, 1);
					else
						LedCodecItem(i, 0);
				}
				break;
			default:
				LedCodecItem(i, 0);
		}
	}
	// driver show	
	DrvDisplay(disp_brightness);
}
void DispSetBrightness(unsigned char level)
{
	disp_brightness = (level <= 7) ? level : 7;
}
unsigned char DispGetBrightness(void)
{
	return disp_brightness;
}
void DispIcon(disp_item_t item_no, disp_mode_t mode)
{
	if (item_no < 0) return;		// item not exist
	if(item_no < LED_ICON_NUM) {
		if (mode & disp_mode_off_icon) {
			disp_buff[item_no][0] = 0;
			mode &= (~disp_mode_off_icon);
		}
		else
			disp_buff[item_no][0] = 1;

		disp_buff[item_no][1] = mode;
	}
}
// 面板显示字符串, str长度必须3
void DispString(const char *str, disp_mode_t mode)
{
	// clear - and .
	DispIcon(disp_item_minus, disp_mode_off_icon | mode);
	DispIcon(disp_item_dot, disp_mode_off_icon | mode);

	for (int i = 0; i < LED_DIGITAL_NUM; i++) {
		disp_buff[disp_item_d1 + i][0] = str[i];
		disp_buff[disp_item_d1 + i][1] = mode;
	}
}
// 只用整数位显示
void DispInt2(int x, disp_mode_t mode)
{
	char buf[LED_DIGITAL_NUM + 1];
	// clear .
	DispIcon(disp_item_dot, disp_mode_off_icon | mode);
	// show minus
	if(x < 0) {
		x = -x;
		DispIcon(disp_item_minus, mode);
	} else 
		DispIcon(disp_item_minus, disp_mode_off_icon | mode);
	if (x >= 99) x = 99;	// 保护一下
	sprintf(buf, "%2d", x);

	for(int i = 0; i < LED_DIGITAL_NUM; i++) {// show number
		disp_buff[disp_item_d1 + i][0] = buf[i]; // buf[2] 天然是0让disp_item_d3不显示
		disp_buff[disp_item_d1 + i][1] = mode;
	}
}
// 扩展到小数位，显示3位整数
void DispInt3(int x, disp_mode_t mode)
{
	char buf[3 + 1];
	// clear .
	DispIcon(disp_item_dot, disp_mode_off_icon | mode);
	// show minus
	if(x < 0) {	
		x = -x;
		DispIcon(disp_item_minus, mode);
	} else 
		DispIcon(disp_item_minus, disp_mode_off_icon | mode);
	if (x >= 999) x = 999;	// 保护一下
	sprintf(buf, "%3d", x);
	for(int i = 0; i < LED_DIGITAL_NUM; i++) {// show number
		disp_buff[disp_item_d1 + i][0] = buf[i];
		disp_buff[disp_item_d1 + i][1] = mode;
	}
}
// display number as %4.1f type
void DispAsFloat(int f, disp_mode_t mode)
{
	if(LED_DIGITAL_NUM < 3) // 只有两位数字, 没有浮点型, 去掉小数位
		DispInt2(f/10, mode);
	else
		DispInt3(f, mode);
	if(f < 10 && f > -10) { // 十位补0
		disp_buff[disp_item_d2][0] = '0';
	}
	DispIcon(disp_item_dot, mode);
}
void DispAllItems(int isOn)
{
	DispString("888", isOn);
	for(int i = 0; i < LED_ICON_NUM; i++){		
		DispIcon(i, isOn);
	}
	DispRefresh();
}


// hal key functions ----------------------------------------------------------------------------------------------- 
// scan 3 key state, 消息上报
void KeyScan(void)
{
	ZqMessage msg;
	uint8_t key = DrvReadKeys();
	// 第一次初始化
	//if(zq_timer_50ms == 0) {
	//	for(int i=0; i<ZQ_KEY_NUM; i++) 
	//		key_state[i] = k_old[i] = 0;
	//}
	for(int i=0; i<ZQ_KEY_NUM; i++){
		msg.param1 = (unsigned short)i;
		msg.param2 = 0;
		uint8_t k_old = (key_state[i] & 0x80000000) ? 1 : 0;
		uint8_t k_new = (key & (1 << i)) ? 1 : 0;
		if(k_old && !k_new){
			//key Down -> UP
			if ((key_state[i] & 0x7fffffff) < 1000) { // press < 1s, is not long pressed, send pressed message
				msg.id = ZQ_EVENT_KEY_PRESSED;
				zqPostMessage(msg);
			}
			key_state[i] = 0; 
			msg.id = ZQ_EVENT_KEY_UP;
			zqPostMessage(msg);
		}
		else if(!k_old && k_new){
			//key Up --> Down
			key_state[i] = 0x80000000; 
			msg.id = ZQ_EVENT_KEY_DOWN;
			zqPostMessage(msg);
		}
		else if(k_old && k_new){
			uint32_t interval = (key_state[i] & 0x7fffffff);
			// key down continue
			interval += KEY_SCAN_PERIOD;
			if (interval > 1000 && (interval % KEY_SCAN_REPEAT_INTERVAL) == 0) { // press > 1s, report key keep every KEY_SCAN_REPEAT_INTERVAL
				msg.id = ZQ_EVENT_KEY_KEEP;
				msg.param2 = interval;
				zqPostMessage(msg);
			}
			key_state[i] = interval | 0x80000000;
		}
		else{
			//key Keep Up
			key_state[i] = 0;
		}
	}
	return;
}
// 返回当前key状态
ZQ_KEY_CODE KeyGetState(ZQ_KEY_ENUM key)
{
	if (key >= ZQ_KEY_NUM)
		return ZQ_EVENT_KEY_UP;
	else if ((key_state[key] & 0x7fffffff) >= 1000)
		return ZQ_EVENT_KEY_KEEP;
	else if(key_state[key] & 0x80000000)
		return ZQ_EVENT_KEY_DOWN;
	else 
		return ZQ_EVENT_KEY_UP;
}
// 返回当前key按下时间, ms
uint16_t KeyGetKeepTime(ZQ_KEY_ENUM key)
{
	if (key >= ZQ_KEY_NUM)
		return 0;
	return key_state[key] & 0x7fffffff;
}
// check no key pressed
int KeyAllReleased(void)
{
	for (int i = 0; i < ZQ_KEY_NUM; i++) 
		if (KeyGetState(i) != ZQ_EVENT_KEY_UP) return 0;
	
	return 1;
}

